﻿using System.Globalization;
using System.Runtime.InteropServices;

namespace Microsoft.Xna.Framework.Input
{
    /// <summary>
    /// Identifies which directions on the directional pad of an Xbox 360 Controller are being pressed.
    /// </summary>
	[StructLayout(LayoutKind.Sequential)]
    public struct GamePadDPad
	{
		#region Fields
		internal ButtonState _up;
		internal ButtonState _right;
		internal ButtonState _down;
		internal ButtonState _left;
		#endregion

		#region Properties
		/// <summary>
		/// Identifies whether the Down direction on the Xbox 360 Controller directional pad is pressed.
		/// </summary>
		public ButtonState Down
		{
			get { return _down; }
		}

		/// <summary>
		/// Identifies whether the Left direction on the Xbox 360 Controller directional pad is pressed.
		/// </summary>
		public ButtonState Left
		{
			get { return _left; }
		}

		/// <summary>
		/// Identifies whether the Right direction on the Xbox 360 Controller directional pad is pressed.
		/// </summary>
		public ButtonState Right
		{
			get { return _right; }
		}

		/// <summary>
		/// Identifies whether the Up direction on the Xbox 360 Controller directional pad is pressed.
		/// </summary>
		public ButtonState Up
		{
			get { return _up; }
		}
		#endregion

        #region Constructor
		/// <summary>
		/// Initializes a new instance of the GamePadDPad class.
		/// </summary>
		/// <param name="upValue">Directional pad up button state.</param>
		/// <param name="downValue">Directional pad down button state.</param>
		/// <param name="leftValue">Directional pad left button state.</param>
		/// <param name="rightValue">Directional pad right button state.</param>
		public GamePadDPad(ButtonState upValue, ButtonState downValue, ButtonState leftValue, ButtonState rightValue)
		{
			_down = downValue;
			_left = leftValue;
			_right = rightValue;
			_up = upValue;
		}
        #endregion

		#region Public Methods
		/// <summary>
		/// Returns a value that indicates whether the current instance is equal to a specified object.
		/// </summary>
		/// <param name="obj">Object with which to make the comparison.</param>
		/// <returns>true if the specified object is equal to this instance; otherwise, false.</returns>
		public override bool Equals(object obj)
		{
			if (obj is GamePadDPad)
				return this == (GamePadDPad)obj;
			return false;
		}

		/// <summary>
		/// Gets the hash code for this instance.
		/// </summary>
		public override int GetHashCode()
		{
			return (((_down.GetHashCode() ^ _left.GetHashCode()) ^ _right.GetHashCode()) ^ _up.GetHashCode());
		}

		/// <summary>
		/// Retrieves a string representation of this object.
		/// </summary>
		public override string ToString()
		{
			string str = string.Empty;
			if (this._up == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "Up";
			}
			if (this._down == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "Down";
			}
			if (this._left == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "Left";
			}
			if (this._right == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "Right";
			}
			if (str.Length == 0)
			{
				str = "None";
			}
			return string.Format(CultureInfo.CurrentCulture, "{{DPad:{0}}}", new object[] { str });
		}
		#endregion

		#region Operators
		/// <summary>
		/// Determines whether two GamePadDPad instances are equal.
		/// </summary>
		/// <param name="left">Object on the left of the equal sign.</param>
		/// <param name="right">Object on the right of the equal sign.</param>
		/// <returns>true of both instance are equal; otherwise, false.</returns>
		public static bool operator ==(GamePadDPad left, GamePadDPad right)
		{
			return ((left._down == right._down) && (left._left == right._left) &&
					(left._right == right._right) && (left._up == right._up));
		}

		/// <summary>
		/// Determines whether two GamePadDPad instances are not equal.
		/// </summary>
		/// <param name="left">Object on the left of the inequal sign.</param>
		/// <param name="right">Object on the right of the inequal sign.</param>
		/// <returns>true if the instances are not equal; otherwise, false.</returns>
		public static bool operator !=(GamePadDPad left, GamePadDPad right)
		{
			return ((left._down != right._down) || (left._left != right._left) ||
					(left._right != right._right) || (left._up != right._up));
		}
		#endregion
	}
}
